package utils

import (
	"github.com/streadway/amqp"
)

const MaxWorkers = 100000

const MaxQueue = 300

//协程池的最小工作单元，即具体业务处理结构体
type Job struct {
	Tag uint64
	Ch *amqp.Channel
	Msg []byte
	Handler func(tag uint64, ch *amqp.Channel, msg []byte)
}

//队列，用来接收、发送请求
var JobQueue chan Job

//用于执行job，可以理解为job的管理者
type Worker struct {
	WorkerPool chan chan Job
	JobChannel chan Job
	quit chan bool
}

//初始化Worker
func NewWorker(workerPool chan chan Job) Worker {
	return Worker {
		WorkerPool:workerPool,
		JobChannel:make(chan Job),
		quit:make(chan bool),
	}
}

//运行Worker
func (w Worker) Start() {
	go func() {
		for {
			//将可用的worker放进队列中
			w.WorkerPool  <- w.JobChannel
			select {
			case job := <- w.JobChannel:
				//接收到具体请求时进行处理
				job.Handler(job.Tag,job.Ch,job.Msg)
			case <-w.quit:
				//接收停止请求
				return
			}
		}
	} ()
}

//发送停止请求
func (w Worker) Stop() {
	go func() {
		w.quit <- true
	}()
}
type Dispatcher struct {
	WorkerPool chan chan Job    //worker的池子，控制worker的数量
	WorkerList []Worker         //worker的切片
}

//根据传入的值，创建对应数量的channel
func NewDispatcher(maxWorkers int) *Dispatcher {
	pool := make(chan chan Job, maxWorkers)
	return &Dispatcher{
		WorkerPool:pool,
	}
}

//根据最大值，创建对应数量的worker
func (d *Dispatcher) Run() {
	for i := 0; i < MaxWorkers; i++ {
		worker := NewWorker(d.WorkerPool)
		worker.Start()
		d.WorkerList = append(d.WorkerList, worker)
	}
	//监听工作队列
	go d.dispatch()
}

func (d *Dispatcher) dispatch() {
	for {
		select {
		case job := <-JobQueue:
			go func (job Job) {
				jobChannel := <-d.WorkerPool
				jobChannel <- job
			}(job)
		}
	}
}

//停止所有的worker
func (d *Dispatcher) Stop() {
	for _, worker := range d.WorkerList {
		worker.Stop()
	}
}
